/**
 * Created by sunjia on 2017/04/05.
 */
package server;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import config.*;


//import entities.ReplyEntity;
import entities.RuleEntity;
import json.ReplyJson;

import entities.TaskEntity;
import entities.TaEntity;
//import json.TaJson;
import json.TaskJson;

import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.query.Query;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.HashMap;


public class ParseServer extends HttpServlet {




    private String mongodbIp;       // --> ? ? ?
    private String mongodbPort;    // ---> ? ? ?
    private String databaseName;   // --> ? ? ?
    public static Datastore mongoDatastore;   //初始化任务队列
    public static String url;   //初始化任务队列
    public boolean init_num=true;

    public java.util.concurrent.BlockingQueue<TaskEntity> blockingQueue = new ArrayBlockingQueue<>(100);  //初始化队列,容量100

    Map<String, RuleEntity> Ta_Map = new HashMap<>();



    public void init() throws ServletException {

        if(init_num==true)
        {
        Properties property = new Properties();
        try {

            property.load(new FileInputStream(ParseServer.class.getClassLoader().getResource("config.inf").getPath()));
            mongodbIp = property.getProperty("mongodbIp","localhost");
            mongodbPort = property.getProperty("mongodbPort","27017");
            databaseName = property.getProperty("databaseName","zhijian");
            url = property.getProperty("url","http://localhost:8081/parser");

        } catch (Exception e) {
            System.err.println("Loading configuration failed, please check. Using default parameters.");
            System.exit(-1);
        }

        MongoDB.setDBConf(databaseName, mongodbIp, "", "", Integer.valueOf(mongodbPort));
        mongoDatastore = MongoDB.instance().getDatabase();
        //初始化任务线程
         List<TaEntity> Ta_Entity_Table = mongoDatastore.createQuery(TaEntity.class).asList();
         for ( TaEntity e : Ta_Entity_Table){
                Ta_Map.put(e.getModelID(),e.getRule());
            }
        TaskThread subtask = new TaskThread(blockingQueue, url,Ta_Map);
            Query<TaskEntity> q = mongoDatastore.createQuery(TaskEntity.class).field("state").equal(false);
        if (q!=null&&q.countAll() > 0)               //判断数据库是否有任务
        {
            blockingQueue.addAll(q.asList());
        }


        subtask.start();
        init_num=false;
       }

    }


    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


            doPost(request, response);

    }


    private boolean checkJson(TaskJson taskJson, ReplyJson results){

        if(taskJson.getModelId()==null||taskJson.getModelId().trim().equals("")){
            results.setRtnCode("1003");
            results.setRtnMsg("收到的Json缺少ModelID字段");
            return false;
        }

        if(taskJson.getXmlDirectory()==null||taskJson.getXmlDirectory().trim().equals("")){
            results.setRtnCode("1004");
            results.setRtnMsg("收到的Json缺少XmlDirectory字段");
            return false;
        }

        if(taskJson.getToFile()==null||taskJson.getToFile().trim().equals("")){
            results.setRtnCode("1005");
            results.setRtnMsg("收到的Json缺少ToFile字段");
            return false;
        }

        if(taskJson.getUuid()==null||taskJson.getUuid().trim().equals("")){
            results.setRtnCode("1006");
            results.setRtnMsg("收到的Json缺少Uuid字段");
            return false;
        }

        return true;
    }

    private boolean checkPath(String path){

        try {
            File file=new File(path);

            if(file.exists()==false) {
                return false;
            }
        }catch(Exception e){
            System.out.print(" Path Not found!"+"\n");
            return false;
        }

        return true;
    }


    private boolean checkUUID(String uuid){


        Query<TaskEntity> q = mongoDatastore.createQuery(TaskEntity.class).field("uuid").equal(uuid);

        if(q!=null&&q.countAll()>0)
            return false;
        return true;
        //return (!q);

    }




    private List<String> checkModelID(String modelID, ReplyJson results){

        String [] ids = modelID.split(",");
        List<String> idlist = new ArrayList<>();

        Set<String> idSet = new HashSet<>();

        for (String str:ids){
            if(idSet.contains(str)){
                results.setRtnCode("1010");
                results.setRtnMsg("modelID 重复");

                return new ArrayList<>();
            }
            idSet.add(str);
        }

        for (String str:ids){
            idlist.add(str.trim());
            Query<TaEntity> q = mongoDatastore.createQuery(TaEntity.class).field("modelID").equal(str.trim());
            if(q!=null && q.countAll()==0) {
                results.setRtnCode("1009");
                results.setRtnMsg("modelID不存在");
                return new ArrayList<>();
            }

        }

        if(idlist.size()==0){
            results.setRtnCode("1009");
            results.setRtnMsg("modelID不存在");
        }

        return idlist;
    }



    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException  {

        //响应request ,检验是否异常，发送发聩，写数据库，将数据库的任务送队列。

        ReplyJson results = new ReplyJson();
        results.setRtnCode("9999");
        results.setRtnMsg("未知错误");

        try {
            req.setCharacterEncoding("ISO-8859-1");

            res.setContentType("text/Json; charset="+ "UTF-8"); //--->??????



            BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream(),"utf-8"));  //----> ? ? ?
            String line = null;
            StringBuilder sb = new StringBuilder();


            while ((line = br.readLine()) != null) {
                sb.append(line);
            }




            String str = sb.toString();

            if(str.equals("")){
                results.setRtnCode("1001");
                results.setRtnMsg("收到的Json为空");
                return;
            }


            TaskJson injson = null;
            System.out.print(str.getClass()+"\n");

            try {
                ObjectMapper objectMapper = new ObjectMapper();
                injson = objectMapper.readValue(str, TaskJson.class);
                //System.out.print(injson.getClass()+"\n");

            } catch (IOException e) {
                e.printStackTrace();
                results.setRtnCode("1002");
                results.setRtnMsg("收到的Json格式不合法");
                return;
            }

            if(checkJson(injson,results)==false){
                return;
            }

            if(checkPath(injson.getXmlDirectory().trim())==false){
                results.setRtnCode("1007");
                results.setRtnMsg("XmlDirectory路径不存在");
                return;
            }

            if(checkUUID(injson.getUuid().trim())==false){
                results.setRtnCode("1008");
                results.setRtnMsg("UUID对应的任务已存在");
                return;
            }

            List<String> ids = checkModelID(injson.getModelId().trim(),results);


            if(ids.size()==0){
                return;
            }

            TaskEntity taskEntity = new TaskEntity();
            taskEntity.setModelId(ids);
            taskEntity.setXmlDirectory(injson.getXmlDirectory());
            taskEntity.setToFile(injson.getToFile());
            taskEntity.setUuid(injson.getUuid());

            //mongoDatastore.save(taskEntity);
            results.setRtnCode("0");
            results.setRtnMsg("成功");
            mongoDatastore.save(taskEntity);
            blockingQueue.put(taskEntity);


        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {

            PrintWriter out = res.getWriter();

            String resultStr = entityToJson(results);
            out.print(resultStr);
            out.close();
        }
    }

    public boolean sendOne(HttpServletResponse res){

        PrintWriter out = null;

        try {
            out = res.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ReplyJson results = new ReplyJson();
        results.setRtnCode("0");
        results.setRtnMsg("成功");
        String resultStr = entityToJson(results);
        out.print(resultStr);
        out.close();
        return true;

    }
    public boolean sendTwo(HttpServletResponse res){

        PrintWriter out = null;

        try {
            out = res.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ReplyJson results = new ReplyJson();
        results.setRtnCode("-9999");
        results.setRtnMsg("模型ID不存在");
        String resultStr = entityToJson(results);
        out.print(resultStr);
        out.close();
        return true;

    }
    public static String entityToJson(ReplyJson results) {

        String json = "{}";
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);
        try {
            json = mapper.writeValueAsString(results);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return json;
    }

//    private static void updateDB(TaskEntity postParam) {
//
//       if(mongoDatastore.createQuery(TaskEntity.class).countAll()>0) {   // PostParamEntity.class ---> ? ?
//            System.out.println("连接数据库成功");
//        }
//        mongoDatastore.delete(mongoDatastore.createQuery(TaskEntity.class)); //mongoDatastore.creteQuery(
////        mongoDatastore.delete(mongoDatastore.createQuery(ReplyJson.class));
//
//        mongoDatastore.save(postParam);
//
//        if(mongoDatastore.createQuery(TaskEntity.class).countAll()>0){
//            System.out.println("更新成功");
//        }
//    }

//    public static  boolean ceshi(String ceshiPath,TaskEntity postParam){
//        try {
//            //File file = new File(("G:\\ProjectMobile\\slu"+postParam.getXmlDirectory().toString().replace("/","\\")).replace("\\","\\\\"));
//            //File file = new File((ceshiPath+postParam.getXmlDirectory().toString().replace("/","\\\\")));
//            File file=new File((ceshiPath+postParam.getXmlDirectory()));
//            //File file = new File(ceshiPath+)
//            if(file.exists()==false) {
//                throw new Exception();
//            }
//        }catch(Exception e){
//            System.out.print(" Path Not found!"+"\n");
//            return false;
//            /*
//            try {
//                throw e;
//            } catch (Exception e1) {
//                e1.printStackTrace();
//            }
//            */
//        }
//        //检测uuid covered
//        try {
//            boolean b2=true;
//            List<TaskEntity> TaskEntity_List = queryTaskEntity();
//            for (TaskEntity e : TaskEntity_List) {
//                if(e.getUuid().equals(postParam.getUuid())){
//                    b2=false;
//                }
//            }
//            if(b2==false){
//                throw new Exception();
//            }
//        }catch(Exception e){
//            System.out.print("uuid covered");
//            return false;
//            /*
//            try {
//                throw e;
//            } catch (Exception e1) {
//                e1.printStackTrace();
//            }
//            */
//        }
//        //检测model是否在表
//        try {
//            boolean a1=true;
//            List<TaEntity> TaEntity_List = queryTaEntity();
//            for (TaEntity e : TaEntity_List) {
//                if(postParam.getModelId().equals(e.getModelID()))
//                {
//                    a1=false;
//                }
//
//            }
//            if(a1==true) throw new Exception();
//        }catch(Exception e){
//            System.out.print("model Not found!"+"\n");
//            return false;
//
//
//        }
//
//     return true;
//    }


    public static List<TaEntity> queryTaEntity()
    {
        List<TaEntity>  q= mongoDatastore.createQuery(TaEntity.class).asList();
        return q;
    }


    public static List<TaskEntity> queryTaskEntity()
    {
        List<TaskEntity> p = mongoDatastore.createQuery(TaskEntity.class).asList();
        return p;

    }

}